package com.hongyun.tms.common.utils;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.api.client.util.Lists;
import com.hongyun.tms.common.dto.SysFileDTO;
import com.hongyun.tms.entity.SysFileBusiness;
import com.hongyun.tms.service.ISysFileBusinessService;
import com.hongyun.tms.service.SysFileService;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 附件处理工具类，提供从业务对象获取附件列表的通用方法。
 */
@Component
public class AttachUtil {

    @Resource
    private ISysFileBusinessService fileBusinessService;

    @Resource
    private SysFileService fileService;

    /**
     * 根据业务ID获取附件列表。
     *
     * @param id          业务ID
     * @param attachClass 附件VO类的类型，用于动态创建附件VO实例
     * @param <T>         附件VO的泛型类型
     * @return 生成的附件VO列表
     */
    public <T> List<T> getAttachList(Long id, Class<T> attachClass) {
        // 查询业务对象关联的文件记录
        List<SysFileBusiness> businessList = fileBusinessService.list(new LambdaQueryWrapper<SysFileBusiness>().in(SysFileBusiness::getBusinessId, id));

        // 提取文件ID集合
        Set<Long> fileIdSet = businessList.stream().map(SysFileBusiness::getFileId).collect(Collectors.toSet());

        // 根据文件ID集合查询文件详细信息
        List<SysFileDTO> fileList = fileService.listByIds(new ArrayList<>(fileIdSet));

        // 创建一个由文件ID映射文件DTO的Map
        Map<Long, SysFileDTO> fileMap = fileList.stream().collect(Collectors.toMap(SysFileDTO::getId, fileDTO -> fileDTO));

        // 用于存储生成的附件VO实例
        List<T> attachList = Lists.newArrayList();

        // 逐个文件ID匹配文件DTO并创建对应的附件VO实例
        for (Long fileId : fileIdSet) {
            SysFileDTO fileDTO = fileMap.get(fileId);
            if (fileDTO != null) {
                String downloadUrl = ServletUriComponentsBuilder.fromCurrentContextPath()
                        .path("/api/internal/file/download/")
                        .path(fileDTO.getFileName())
                        .toUriString();
                T attach = createAttachInstance(fileId, fileDTO, downloadUrl, attachClass);
                attachList.add(attach);
            }
        }

        return attachList;
    }

    /**
     * 动态创建附件VO实例。
     *
     * @param fileId      文件ID
     * @param fileDTO     文件DTO，包含文件的详细信息
     * @param minioUrl    MinIO存储服务的URL，用于生成文件的访问URL
     * @param attachClass 附件VO类的类型，用于动态创建附件VO实例
     * @param <T>         附件VO的泛型类型
     * @return 生成的附件VO实例
     */
    private <T> T createAttachInstance(Long fileId, SysFileDTO fileDTO, String minioUrl, Class<T> attachClass) {
        try {
            // 使用反射创建附件VO实例，传递构造函数所需的参数
            return attachClass.getDeclaredConstructor(String.class, String.class, String.class)
                    .newInstance(minioUrl, fileId.toString(), fileDTO.getBusinessType());
        } catch (Exception e) {
            throw new RuntimeException("创建附件实例时发生错误", e);
        }
    }
}
